<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务，帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2024 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace app\common\library\collector\provider\driver;

use app\common\enum\goods\SpecType as GoodsSpecTypeEnum;
use app\common\library\collector\provider\Driver;
use cores\exception\BaseException;

/**
 * 淘宝商品采集驱动
 * Class Taobao
 * @package app\common\library\collector\provider\driver
 */
class Taobao extends Driver
{
    // API地址
    const API_URL = 'https://api09.99api.com/taobao/detailv2';

    /**
     * 获取商品详情
     * @param string $itemId
     * @return array
     * @throws BaseException
     */
    public function detail(string $itemId): array
    {
        $result = $this->curlGet(self::API_URL, $itemId);
        return $this->formatGoods($result['data']);
    }

    /**
     * 格式化商品数据
     * @param array $original
     * @return array
     */
    private function formatGoods(array $original): array
    {
        $data = [];
        // 商品规格 (SKU数量为1时是单规格，大于1是多规格)
        $data['spec_type'] = !empty($original['item']['props']) ? GoodsSpecTypeEnum::MULTI : GoodsSpecTypeEnum::SINGLE;
        $data['goods_name'] = $original['item']['title'];
        $data['goodsImages'] = $this->goodsImages($original['item']['images']);
        // 商品详情内容
        if (isset($original['item']['descImgs'])) {
            $data['content'] = $this->goodsContent($original['item']['descImgs']);
        }
        // 整理多规格数据
        if ($data['spec_type'] === GoodsSpecTypeEnum::MULTI) {
            \array_shift($original['item']['sku']);
            $specList = $this->createSpecList($original['item']['props']);
            $data['specData']['specList'] = $specList;
            $data['specData']['skuList'] = $this->createSkuList($original['item']['sku'], $specList);
        } elseif ($data['spec_type'] === GoodsSpecTypeEnum::SINGLE) {
            $skuInfo = \current($original['item']['sku']);
            $data['goods_price'] = $skuInfo['price'];
            $data['line_price'] = '0.00';
            $data['stock_num'] = $skuInfo['quantity'];    // 库存数量
            $data['goods_weight'] = 1;                    // 重量默认1kg
        }
        return $data;
    }

    /**
     * 创建标准的商品SKU数据
     * @param array $originalSkuList 商品SKU列表
     * @param array $specList 商品规格
     * @return array
     */
    private function createSkuList(array $originalSkuList, array $specList): array
    {
        // 根据规格数据生成完整的SKU数据 (因为originalSkuList会有不存在的sku)
        $cartesian = $this->cartesian($specList);
        // 整理商品SKU列表
        $skuList = [];
        foreach ($cartesian as $spec) {
            // 设置skuKeys数据
            $skuKeys = [];
            foreach ($spec as $specValue) {
                $skuKeys[] = [
                    'groupKey' => $specValue['groupKey'],
                    'valueKey' => $specValue['key']
                ];
            }
            // 查找已存在的SKU
            $originalSku = $this->findOriginalSku($originalSkuList, $spec);
            // 整理SKU数据
            $skuList[] = [
                'image_id' => 0,
                'goods_price' => $originalSku ? $originalSku['price'] : '0.00',
                'line_price' => '0.00',
                'stock_num' => $originalSku ? $originalSku['quantity'] : 100,    // 库存数量
                'goods_weight' => 1,    // 重量默认1kg
                'goods_sku_no' => $originalSku ? $originalSku['skuId'] : '',
                'skuKeys' => $skuKeys,
                'imageUrl' => $originalSku ? $this->imageUrl($originalSku['image'], '_800x800.jpg') : '',
            ];
        }
        return $skuList;
    }

    /**
     * 查找已存在的SKU
     * @param array $originalSkuList
     * @param array $spec
     * @return false|mixed
     */
    private function findOriginalSku(array $originalSkuList, array $spec)
    {
        foreach ($originalSkuList as $item) {
            $temp = 0;
            foreach ($spec as $specValue) {
                if (\mb_strpos($item['skuName'], $specValue['spec_value']) !== false) {
                    $temp++;
                }
            }
            if ($temp === \count($spec)) {
                return $item;
            }
        }
        return false;
    }

    /**
     * 生成完整的SKU列表（笛卡尔积运算）
     * @param array $specList
     * @param array $tmp
     * @param array $nArr
     * @return int
     */
    private function cartesian(array $specList, array $tmp = [], array $nArr = [])
    {
        foreach (array_shift($specList)['valueList'] as $v) {
            $tmp[] = $v;
            if ($specList) {
                $nArr = $this->cartesian($specList, $tmp, $nArr);
            } else {
                $nArr[] = $tmp;
            }
            array_pop($tmp);
        }
        return $nArr;
    }

    /**
     * 创建标准的商品规格数据（树状）
     * @param array $props 规格信息
     * @return array
     */
    private function createSpecList(array $props): array
    {
        $specList = [];
        foreach ($props as $prop) {
            $groupKey = \count($specList);
            $valueList = [];
            foreach ($prop['values'] as $value) {
                $valueList[] = [
                    'key' => \count($valueList),
                    'groupKey' => $groupKey,
                    'spec_value' => $value['name'],
                ];
            }
            $specList[] = [
                'key' => $groupKey,
                'spec_name' => $prop['name'],
                'valueList' => $valueList,
            ];
        }
        return $specList;
    }

    /**
     * 格式化商品主图
     * @param array $images
     * @return array
     */
    private function goodsImages(array $images): array
    {
        return array_map(function (string $imageUrl) {
            return $this->imageUrl($imageUrl, '_800x800.jpg');
        }, \array_slice($images, 0, 10));
    }

    /**
     * 格式化图片url
     * @param string $url 图片url
     * @param string $suffix 后缀 (目的是格式化图片尺寸和压缩文件体积)
     * @return string
     */
    private function imageUrl(string $url, string $suffix = ''): string
    {
        if (empty($url)) {
            return '';
        }
        // 补全url协议
        if (\substr($url, 0, 2) === '//') {
            return "https:{$url}{$suffix}";
        }
        if (\substr($url, 0, 4) != 'http') {
            return "https://{$url}{$suffix}";
        }
        // http替换为https
        return str_replace('http://', 'https://', $url) . $suffix;
    }

    /**
     * 格式化商品详情
     * @param array $descImgs
     * @return string
     */
    private function goodsContent(array $descImgs): string
    {
        $content = '';
        foreach ($descImgs as $img) {
            $content .= "<p><img src=\"{$img}\"/></p>";
        }
        return $content;
    }
}